using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Labirinto_Magico
{
    enum STATES
    {
        T0,
        T1,
        T2,
        T3,
        N,
        R,
        I,
        P, 
        M,
        RI
    }

    public class Tutorial : Microsoft.Xna.Framework.DrawableGameComponent
    {
        GameGUIHandler mGUI;
        GameGuiRender mGUIRender;

        bool mNextTurn = false;

        STATES mState;
        bool mTutorialModeActive = true;

        GameRender mRender;
        SoundHandler mSound;

        public Tutorial(Game game)
            : base(game)
        {

        }

        public override void Initialize()
        {
            LabyrinthGameState.gameState = LabyrinthGameState.State.Init(1, 1, Game.GraphicsDevice.Viewport.Height * 0.111111f);
            
            RenderingData renderWrapper = (RenderingData)Game.Services.GetService(typeof(RenderingData));
            mSound = (SoundHandler)Game.Services.GetService(typeof(SoundHandler));

            mRender = new GameRender(renderWrapper);

            for (int i = 0; i < LabyrinthGameState.gameState.mPlayers.Length; ++i)
            {
                Player.Player p = LabyrinthGameState.gameState.mPlayers.ElementAt(i);
                p.mGoal = GameLogicFunctions.GetNextGoal(p.mPosition, p);
            }

            mSound.StartSound();
            mGUI = new GameGUIHandler();
            mGUI.InitGUI(Game, LabyrinthGameState.gameState, Game.GraphicsDevice.Viewport.Height * 0.111111f, LabyrinthGameState.gameState.mRemainedTile, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height);
            mGUIRender = new GameGuiRender(renderWrapper, Game.GraphicsDevice.Viewport);

            mState = STATES.T0;

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            if (mGUI.mPause.PressButton())
            {
                mSound.ButtonSound();
                mSound.StopTutorial();
                Game.Components.Remove(this);
                Game.Components.Add(new MainMenu(Game));
                mSound.StopTutorial();
            }
            else
                TutorialUpdate(gameTime);

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            SI.LOGIC_GAME_STATE state = SI.LOGIC_GAME_STATE.RI;
            if (mState == STATES.P || mState == STATES.M || mState == STATES.T2)
                state = SI.LOGIC_GAME_STATE.M;

            mRender.DrawChessboard(state, LabyrinthGameState.gameState.mSelectedTile, LabyrinthGameState.gameState.mRemainedTile);

            mRender.DrawPlayers(GraphicsDevice.Viewport);

            mGUIRender.DrawCPs(mGUI.mChessboard.mControlPoints);
            mGUIRender.DrawScore(LabyrinthGameState.gameState.mSelectedPlayer, mGUI.mScore);
            mGUIRender.DrawButton(mGUI.mPause);

            if (LabyrinthGameState.gameState.mWinner)
                mGUIRender.DrawVictory(LabyrinthGameState.gameState.mSelectedPlayer, mGUI.mTurnAndVictory);

            base.Draw(gameTime);
        }

        void TutorialUpdate(GameTime gameTime)
        {
            if (LabyrinthGameState.gameState.mWinner)
            {
                if (!mSound.PlayTutorial(mSound.mTutorial.Part_5, gameTime.TotalGameTime))
                    return;
                Game.Components.Remove(this);
                Game.Components.Add(new MainMenu(Game));
            }
            else
            {
                switch (mState)
                {
                case STATES.T0:
                    if (mSound.PlayTutorial(mSound.mTutorial.Part_1, gameTime.TotalGameTime))
                        mState = STATES.R;
            	    break;
                case STATES.T1:
                    if (mSound.PlayTutorial(mSound.mTutorial.Part_2, gameTime.TotalGameTime))
                        mState = STATES.I;
            	    break;
                case STATES.T2:
                    Player.Player p0 = LabyrinthGameState.gameState.mSelectedPlayer;
                    p0.mPathFinder.PathFinding(p0.mPosition, p0.mGoal, LabyrinthGameState.gameState.mChessboard);
                    if (mSound.PlayTutorial(mSound.mTutorial.Part_3, gameTime.TotalGameTime))
                        mState = STATES.P;
            	    break;
                case STATES.T3:
                    if (mSound.PlayTutorial(mSound.mTutorial.Part_4, gameTime.TotalGameTime))
                    {
                        mTutorialModeActive = false;
                        mState = STATES.N;
                    }
            	    break;
                case STATES.N:
                    if (NextTurn(gameTime.TotalGameTime))
                        mState = STATES.RI;
                    break;
                case STATES.R:
                    if (mGUI.mChessboard.mRemainedTile.PressButton()) 
                    {
                        GameLogicFunctions.RotateRemainedTile();

                        mSound.ButtonSound();

                        if (mTutorialModeActive)
                            mState = STATES.T1;
                        else
                            mState = STATES.I;
                    }
            	    break;
                case STATES.I:
                    GUICPButton cpButton = mGUI.mChessboard.UpdateCPButton(gameTime);
                    if (cpButton != null)
                    {
                        SI.POSITION insertPos = cpButton.mType;
                        int sequencePos = cpButton.mSequencePosition;
                        GameLogicFunctions.InsertTile(insertPos, sequencePos);
                        mGUI.mChessboard.UpdateAssociatedTiles();

                        mSound.SliderSound();

                        if (mTutorialModeActive)
                            mState = STATES.T2;
                        else
                            mState = STATES.P;
                    }
                    break;
                case STATES.P:
                    GUIChessboardButton selectedTile = mGUI.mChessboard.UpdateSelectedTile(gameTime);
                    if (selectedTile != null)
                    {
                        if (LabyrinthGameState.gameState.mSelectedPlayer.mPathFinder.IsTileInTree(selectedTile.mAssociatedTile))
                        {
                            LabyrinthGameState.gameState.mSelectedTile = selectedTile.mAssociatedTile;
                            mState = STATES.M;
                        }
                        else
                            mSound.ErrorSound();
                    }
                    else
                        GameLogicFunctions.UpdatePathFindingToGoal();
            	    break;
                case STATES.M:
                    if (GameLogicFunctions.UpdateMoveToGoal(gameTime, LabyrinthGameState.gameState.mSelectedTile))
                    {
                        if (mTutorialModeActive)
                            mState = STATES.T3;
                        else
                            mState = STATES.RI;
                    }
                    break;
                case STATES.RI:
                    if (mGUI.mChessboard.mRemainedTile.PressButton())
                    {
                        GameLogicFunctions.RotateRemainedTile();
                        mSound.ButtonSound();
                    }
                    GUICPButton cpButton1 = mGUI.mChessboard.UpdateCPButton(gameTime);
                    if (cpButton1 != null)
                    {
                        SI.POSITION insertPos = cpButton1.mType;
                        int sequencePos = cpButton1.mSequencePosition;
                        GameLogicFunctions.InsertTile(insertPos, sequencePos);
                        mGUI.mChessboard.UpdateAssociatedTiles();

                        mSound.SliderSound();

                        mState = STATES.P;
                    }
                    break;
                }
            }
        }

        public bool NextTurn(TimeSpan iTime)
        {
            if (mGUI.mTurnAndVictory.TimePassed(iTime, 2))
            {
                return true;
            }
            else
                return false;
        }

    }
}
